import traceback

from functools import wraps

from utils.log import Log
from utils.error import *


class ClassHandler(Log):
    cache = {'a': 1}

    def __new__(cls, *args, **kwargs):
        instance = super().__new__(cls)
        # cls.cache = {'a': 1}
        return instance

    def __init__(self, timeout=5, end=False):
        super(ClassHandler, self).__init__()
        self.timeout = timeout
        self.end = end

    def cache_key(self, function, *args, **kwargs):
        return f"{function.__module__}::{function.__qualname__}(" \
               f"{self.parameters_to_string(args, kwargs)})"

    def __call__(self, function):
        @wraps(function)
        def wrapper(*args, **kwargs):
            is_fail = False
            if len(args) and isinstance(args[0], Log):
                this = args[0]
                nargs = args
            else:
                this = Log()
                nargs = args
            try:
                self.debug(f"{self.cache_key(function, nargs, kwargs)} enter")
                return function(*args, **kwargs)
            except Exception as e:
                is_fail = True
                if isinstance(e, SimpleError):
                    err = e
                else:
                    tb = traceback.format_exc()
                    err = this.simple_error(tb, end=self.end)
                if self.end:
                    return err
                else:
                    raise err
            finally:
                if is_fail:
                    if hasattr(this, "rollback"):
                        this.rollback()
                self.debug(f"{self.cache_key(function, nargs, kwargs)} exit")

        return wrapper

    def __del__(self):
        self.info(f"timeout {self.timeout}, cache {self.cache}")
